package com.demo.sender.email;

import cn.hutool.core.convert.Convert;
import com.alibaba.fastjson2.JSON;
import com.demo.common.ResultData;
import com.demo.config.HttpConfig;
import lombok.extern.slf4j.Slf4j;
import okhttp3.*;
import org.apache.commons.lang3.ObjectUtils;
import org.apache.commons.lang3.exception.ExceptionUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.scheduling.annotation.Async;
import org.springframework.scheduling.concurrent.ThreadPoolTaskExecutor;
import org.springframework.stereotype.Component;

import javax.naming.ServiceUnavailableException;
import java.util.List;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.Future;
import java.util.concurrent.TimeUnit;

/**
 * @author wangfengchen
 */
@Component
@Slf4j
public class MailGunEmailBasicSender {


  /**
   * 最大重试次数
   */
  private static final int MAX_RETRIES = 3;

  private static final int connectTimeout = 2000;
  private static final int readTimeout = 2000;
  private static final int writeTimeout = 2000;
  private static final String url = "https://api.mailgun.net/v3/email.newhuotech.com/messages";


  @Value("${email.mailGun.apiKey:not_set}")
  private String apiKey;
  @Value("${email.mailGun.source:not_set}")
  private String source;

  @Autowired
  private ThreadPoolTaskExecutor threadPoolTaskExecutor;
  @Autowired
  private HttpConfig httpConfig;


  private final OkHttpClient.Builder okHttpClientBuilder;

  public MailGunEmailBasicSender() {
    this.okHttpClientBuilder = getBuilder(connectTimeout, readTimeout, writeTimeout);
  }

  static OkHttpClient.Builder getBuilder(long connectTimeout, long readTimeout, long writeTimeout) {
    return new OkHttpClient.Builder()
        .connectionPool(new ConnectionPool(20, 50, TimeUnit.SECONDS))
        .readTimeout(readTimeout, TimeUnit.MILLISECONDS)
        .connectTimeout(writeTimeout, TimeUnit.MILLISECONDS)
        .writeTimeout(connectTimeout, TimeUnit.MILLISECONDS);
  }

  /**
   * 发送邮件
   *
   * @param toAddresses 接收者电子邮件地址列表
   * @param subject     邮件主题
   * @param bodyHtml    邮件HTML正文
   * @param bodyText    邮件文本正文（可选）
   * @return SendEmailResponse 响应对象
   */
  public ResultData<Object> send(String toAddresses, String subject, String bodyHtml, String bodyText) {
    //  添加认证
//    if (StringUtils.isNotBlank(apiKey)) {
//      okHttpClientBuilder.authenticator((route, response) -> {
//        String credential = Credentials.basic("api", apiKey);
//        return response.request().newBuilder().header("Authorization", credential).build();
//      });
//    }
    OkHttpClient okHttpClient = httpConfig.getOkHttpClient();
    HttpUrl httpUrl = HttpUrl.parse(url);
    if (ObjectUtils.isEmpty(httpUrl)) {
      log.error("httpUrl is null");
      return null;
    }
    RequestBody requestBody = new FormBody.Builder()
        .add("from", source)
        .add("to", toAddresses)
        .add("subject", subject)
        .add("html", bodyHtml)
        .add("o:tracking", "false")
        .build();
    String credential = Credentials.basic("api", apiKey);
    Request request = new Request.Builder()
        .url(httpUrl)
        .addHeader("Authorization", credential)
        .post(requestBody)
        .build();
    try (Response response = okHttpClient.newCall(request).execute()) {
      ResponseBody body = response.body();
      String resp = body == null ? null : body.string();
      log.info("response = {}", resp);
      return ResultData.success(getMessageId(resp));
    } catch (Exception e) {
      handleSendEmailException(e, toAddresses);
      return ResultData.fail();
    }

  }

  public ResultData<Object> sendList(List<String> toAddresses, String subject, String bodyHtml, String bodyText) {
    return null;
  }

  /**
   * 异步发送邮件
   *
   * @param toAddresses 接收者电子邮件地址列表
   * @param subject     邮件主题
   * @param bodyHtml    邮件HTML正文
   * @param bodyText    邮件文本正文（可选）
   * @return SendEmailResponse 响应对象
   */
  @Async
  public ResultData<Object> sendAsync(String toAddresses, String subject, String bodyHtml, String bodyText) {
    Future<String> future = threadPoolTaskExecutor.submit(() -> {
      try {
        ResultData<Object> resultData = null;
        int retryCount = 0;
        while (retryCount < MAX_RETRIES) {
          try {
            resultData = send(toAddresses, subject, bodyHtml, bodyText);
            log.info("sendEmail resp = {}", resultData);
            break;
          } catch (Exception e) {
            if (!(e.getCause() instanceof ServiceUnavailableException)) {
              throw e;
            }
            log.info("Retrying due to service unavailable", e);
            retryCount++;
          }
        }
        if (ObjectUtils.isEmpty(resultData)) {
          return null;
        }
        return resultData.getData().toString();
      } catch (Exception e) {
        handleSendEmailException(e, toAddresses);
        return null;
      }
    });
    if (ObjectUtils.isEmpty(future)) {
      return ResultData.fail();
    }
    String messageId = null;
    try {
      messageId = future.get();
    } catch (InterruptedException | ExecutionException e) {
      throw new RuntimeException(e);
    }
    return ResultData.success(messageId);
  }

  /**
   * 处理发送邮件异常
   *
   * @param e           异常对象
   * @param toAddresses
   */
  private void handleSendEmailException(Exception e, String toAddresses) {
    // 这里可以添加自定义的日志记录或异常处理逻辑
    log.info("handleSendEmailException error，toAddresses = {}，error = {}", toAddresses, ExceptionUtils.getStackTrace(e));
    // 其他业务处理
  }

  /**
   * 获取消息唯一ID
   *
   * @param body
   * @return
   */
  private String getMessageId(String body) {
    if (body == null || !body.startsWith("{")) {
      return null;
    }
    return Convert.toStr(JSON.parseObject(body).get("id"));
  }


}

